home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 85 / CD Temático 40 Febrero 2004.iso / DOS / ntfs / dos / hdaccess.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-02-15  |  13.9 KB  |  544 lines

  1. /*
  2.  
  3.     File: hdaccess.c
  4.  
  5.     Copyright (C) 1998-2001  Christophe Grenier <grenier@nef.esiea.fr>
  6.   
  7.     This software is free software; you can redistribute it and/or modify
  8.     it under the terms of the GNU General Public License as published by
  9.     the Free Software Foundation; either version 2 of the License, or
  10.     (at your option) any later version.
  11.   
  12.     This program is distributed in the hope that it will be useful,
  13.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.     GNU General Public License for more details.
  16.   
  17.     You should have received a copy of the GNU General Public License
  18.     along with this program; if not, write to the Free Software
  19.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  
  21.  */
  22.  
  23. #define LINUX_WRITE 1
  24. #ifdef LINUX_WRITE
  25. #define open_mode O_RDWR
  26. #else
  27. #define open_mode O_RDONLY
  28. #endif
  29. #ifdef DJGPP
  30. #include <stdlib.h>     /* atexit */
  31. #include <stdio.h>
  32. #include <go32.h>       /* dosmemget/put */
  33. #include <dpmi.h>
  34. #include <bios.h>       /* bios_k* */
  35. #include "types.h"
  36. #include "common.h"
  37. #include "fnctdsk.h"
  38. #include "hdaccess.h"
  39. //#include "interface.h"
  40. #define HD_RW_BUF_SIZ 0x10
  41. #define HDPARM_BUF_SIZ 0x1A
  42. #define MAX_IO_NBR 10
  43. #define PARA_CMD         8
  44. int hd_super(int, t_param_disk_cst, int, int, int, int, void*);
  45. int hd_identify_bios(t_param_disk param_disk);
  46. int hd_identify_enh_bios(t_param_disk param_disk);
  47. int check_enh_bios(t_param_disk param_disk, const int debug);
  48. static int dos_segment = 0;
  49. static int dos_selector = 0;
  50.  
  51. void free_dos_buffer(void)
  52. {
  53.   __dpmi_free_dos_memory(dos_selector);
  54.   dos_segment = dos_selector = 0;
  55. }
  56.  
  57. int alloc_dos_buffer(void)
  58. {
  59.   if (dos_segment)
  60.     return 0;
  61.   if ((dos_segment = __dpmi_allocate_dos_memory(18*512/16, &dos_selector))== -1)
  62.   {
  63.     dos_segment = 0;
  64.     return 1;
  65.   }
  66.   atexit(free_dos_buffer);
  67.   return 0;
  68. }
  69.  
  70. int hd_super(int cmd, t_param_disk_cst disk_car, int head, int track, int sector, int nsects, void *buffer)
  71.   __dpmi_regs r;
  72.   uchar buf[HD_RW_BUF_SIZ];
  73.   int dos_segment2, dos_selector2, xfer2=nsects*512;
  74. #ifdef DEBUG
  75.   printf("hd_super cmd=%d track=%d head=%d sector=%d\n",cmd,track,head,sector);
  76. #endif
  77.   if(disk_car->mode==0)
  78.   { // Limite CHS= 1023,255,63 = 8,064Mo ~= 7.8 Go
  79.     if(track<1024)
  80.       return biosdisk(cmd, disk_car->disk, head, track, sector, nsects, buffer);
  81.     return 1;
  82.   }
  83.   if(dos_segment==0)
  84.     if(alloc_dos_buffer())
  85.       return 1;
  86.   if ( (dos_segment2=__dpmi_allocate_dos_memory((xfer2 + 15) >> 4, &dos_selector2)) == -1 )
  87.     return 1;
  88.   *(word*)&buf[0]=HD_RW_BUF_SIZ;
  89.   *(word*)&buf[2]=nsects;
  90.   *(dword*)&buf[0x4]=dos_segment2<<16;
  91.   *(dword*)&buf[0x8]=(track*(disk_car->CHS.head+1)+head)* disk_car->CHS.sector+sector-1;
  92.   *(dword*)&buf[0xC]=0;
  93.  
  94.   r.x.ds = dos_segment;
  95.   r.x.si = 0;
  96.   r.h.dl = disk_car->disk;
  97.   switch(cmd)
  98.   {
  99.     case 2:
  100.       r.h.ah = 0x42;
  101.       break;
  102.     case 3:
  103.       r.x.ax = 0x4300;
  104.       dosmemput(buffer,xfer2,dos_segment2<<4);
  105.       break;
  106.     case 0x0C:
  107.       r.h.ah = 0x47;
  108.       break;
  109.   }
  110.   dosmemput(&buf, HD_RW_BUF_SIZ, dos_segment<<4);
  111.   __dpmi_int(0x13, &r);
  112.   if(cmd==2)
  113.     dosmemget(dos_segment2<<4, xfer2, buffer);
  114.   __dpmi_free_dos_memory(dos_selector2);
  115. #ifdef DEBUG
  116.   if(r.h.ah)
  117.   {
  118.     doprintf(" %ld err %02X %04X\n",*(dword*)&buf[0x8], r.h.ah,r.x.flags);
  119.   }
  120. #endif
  121.   return r.h.ah;
  122. }
  123.  
  124. int check_enh_bios(t_param_disk param_disk, const int debug)
  125. {
  126.   __dpmi_regs r;
  127.   r.h.ah = 0x41;
  128.   r.x.bx = 0x55AA;
  129.   r.h.dl = param_disk->disk;
  130.   __dpmi_int(0x13, &r);
  131.   if(r.x.bx != 0xAA55)  /* INT 13 Extensions not installed */
  132.     return 0;
  133.   if(debug)
  134.   {
  135.     printf("Disk %02X\n",param_disk->disk);
  136.     switch(r.h.ah)
  137.     {
  138.       case 0x01:
  139.         printf("Enhanced BIOS 1.x\n");
  140.         break;
  141.       case 0x20:
  142.         printf("Enhanced BIOS 2.0 / EDD-1.0\n");
  143.         break;
  144.       case 0x21:
  145.         printf("Enhanced BIOS 2.1 / EDD-1.1\n");
  146.         break;
  147.       case 0x30:
  148.         printf("Enhanced BIOS EDD-3.0\n");
  149.         break;
  150.       default:
  151.         printf("Enhanced BIOS unknow %02X\n",r.h.ah);
  152.         break;
  153.     }
  154.     if((r.x.cx & 1)!=0)
  155.       printf("Extended disk access functions R/W/I Ok\n");
  156.     if((r.x.cx & 4)!=0)
  157.       printf("Enhanced disk drive (EDD) functions identify Ok\n");
  158.   }
  159.   return ((r.x.cx&1)!=0);
  160. }
  161.  
  162. int hd_identify_enh_bios(t_param_disk param_disk)
  163. {
  164.   __dpmi_regs r;
  165.   uchar buf[HDPARM_BUF_SIZ];
  166.   buf[0]=HDPARM_BUF_SIZ;
  167.   buf[1]=0;
  168.   if(dos_segment==0)
  169.     if(alloc_dos_buffer())
  170.       return 1;
  171.   r.h.ah = 0x48;
  172.   r.x.ds = dos_segment;
  173.   r.x.si = 0;
  174.   r.h.dl = param_disk->disk;
  175.   dosmemput(&buf, HDPARM_BUF_SIZ, dos_segment<<4);
  176.   __dpmi_int(0x13, &r);
  177.   dosmemget(dos_segment<<4, HDPARM_BUF_SIZ, &buf);
  178.   if(r.h.ah)
  179.     return 1;
  180.   param_disk->CHS.cylinder=*(word*)&buf[0x04];
  181.   param_disk->CHS.head=*(word*)&buf[0x08];
  182.   param_disk->CHS.sector=*(word*)&buf[0x0C];
  183.   if(param_disk->CHS.cylinder)
  184.   {
  185.     param_disk->CHS.cylinder--;
  186.     param_disk->CHS.head--;
  187.   }
  188.   else
  189.   {   /* ATTENTION qword en fait */
  190.     param_disk->CHS.cylinder=(*(dword*)&buf[0x10]/255)/63-1;
  191.     param_disk->CHS.head=255-1;
  192.     param_disk->CHS.sector=63;
  193.   }
  194. #ifdef DEBUG
  195.   printf("hd_identify_enh_bios\n");
  196. #endif
  197. //  aff_disk_rapport(param_disk);
  198.   return 0;
  199. }
  200.  
  201. int hd_identify_bios(t_param_disk param_disk)
  202. {
  203.   uchar buf[0x200];
  204.   if(biosdisk(PARA_CMD,param_disk->disk,0,0,1,1,buf))
  205.     return 1;
  206.   param_disk->CHS.cylinder=((buf[0] & 0x0C0)<<2)|buf[1];
  207.   param_disk->CHS.head=buf[3];
  208.   param_disk->CHS.sector=buf[0] & 0x3F;
  209. #ifdef DEBUG
  210.   printf("hd_identify_bios\n");
  211. #endif
  212. //  aff_disk_rapport(param_disk);
  213.   return 0;
  214. }
  215.  
  216. int hd_identify(t_param_disk param_disk, const int debug)
  217. {
  218.   int err=1;
  219.   param_disk->mode=check_enh_bios(param_disk,debug);
  220.   if(!hd_identify_bios(param_disk))
  221.   {
  222.     err=0;
  223.     if(!biosdisk(0x0C, param_disk->disk, param_disk->CHS.head, param_disk->CHS.cylinder+1, param_disk->CHS.sector, 0, NULL))
  224.     {
  225.       param_disk->CHS.cylinder++;
  226.       if(debug)
  227.         printf("BIOS hides the last sector.\n");
  228.     }
  229.   }
  230.   if(param_disk->mode)
  231.     return hd_identify_enh_bios(param_disk);
  232.   return err;
  233. }
  234.  
  235. int hd_read(t_param_disk_cst disk_car,const uint nbr_secteur, void *nom_buffer, t_disk_cst lieu)
  236. {
  237.   int i,rc=-1;
  238.   for(i=0;(rc!=0) && (i<MAX_IO_NBR);i++)
  239.     rc=hd_super(2, disk_car, lieu->head, lieu->cylinder, lieu->sector, nbr_secteur, nom_buffer);
  240.   /*
  241.   for(i=0;i<0x10;i++)
  242.     printf("%02X ",*(char*)(nom_buffer+i));
  243.   printf("\n");
  244.   fflush(stdout);
  245.   */
  246.   return rc;
  247. }
  248.  
  249. int hd_read2(t_param_disk_cst disk_car,const uint nbr_secteur, void *nom_buffer, t_diskext_cst lieu)
  250. {
  251.   int i,rc=-1;
  252.   for(i=0;(rc!=0) && (i<MAX_IO_NBR);i++)
  253.     rc=hd_super(2, disk_car, lieu->start.head, lieu->start.cylinder, lieu->start.sector, nbr_secteur, nom_buffer);
  254. #ifdef DEBUG
  255.   for(i=0;i<0x10;i++)
  256.     printf("%02X ",*(char*)(nom_buffer+i));
  257.   printf("\n");
  258.   fflush(stdout);
  259. #endif
  260.   return rc;
  261. }
  262.  
  263. int hd_write(t_param_disk_cst disk_car,const uint nbr_secteur, void *nom_buffer, t_disk_cst lieu)
  264. {
  265.   int i,rc=-1;
  266.   for(i=0;(rc!=0)&&(i<MAX_IO_NBR);i++)
  267.     rc=hd_super(3, disk_car, lieu->head, lieu->cylinder, lieu->sector, nbr_secteur, nom_buffer);
  268.   return rc;
  269. }
  270.  
  271. int hd_write2(t_param_disk_cst disk_car,const uint nbr_secteur, void *nom_buffer, t_diskext_cst lieu)
  272. {
  273.   int i,rc=-1;
  274.   for(i=0;(rc!=0)&&(i<MAX_IO_NBR);i++)
  275.     rc=hd_super(3, disk_car, lieu->start.head, lieu->start.cylinder, lieu->start.sector, nbr_secteur, nom_buffer);
  276.   return rc;
  277. }
  278.  
  279. int hd_parse(t_param_disk param_disk[NBR_DISK_MAX],const int debug)
  280. {
  281.   int i;
  282.   int nbr_disk=0;
  283.   for(i=0x80;i<0x88;i++)
  284.   {
  285.     param_disk[nbr_disk]->disk=i;
  286.     if(!hd_identify(param_disk[nbr_disk],debug))
  287.       nbr_disk++;
  288.   }
  289.   return nbr_disk;
  290. }
  291. #elif defined(LINUX)
  292. #include <unistd.h>
  293. #include <sys/ioctl.h>
  294. #include <linux/hdreg.h>
  295. #include <fcntl.h> 
  296. #include <sys/mount.h>
  297. #include <string.h>
  298. #include "types.h"
  299. #include "common.h"
  300. #include "fnctdsk.h"
  301. #include "hdaccess.h"
  302.  
  303. loff_t llseek(int,loff_t, int);
  304. /* if llseek don't work well, try lseek64 */
  305.  
  306. int hd_read(t_param_disk_cst disk_car,const uint nbr_secteur, void *nom_buffer, t_disk_cst lieu)
  307. {
  308.   int i;
  309.   loff_t pos;
  310.   pos=((loff_t) get_LBA(disk_car,lieu))<<9;
  311.   i=llseek(lieu->disk,pos,SEEK_SET);
  312.   if(i==-1)
  313.     return -1;
  314.   if(read(lieu->disk, nom_buffer, nbr_secteur*0x200)==-1)
  315.     return -1;
  316.   return 0;
  317. }
  318.  
  319. int hd_write(t_param_disk_cst disk_car,const uint nbr_secteur, void *nom_buffer, t_disk_cst lieu)
  320. {
  321. #ifdef LINUX_WRITE
  322.   int i;
  323.   loff_t pos;
  324.   pos=((loff_t) get_LBA(disk_car,lieu))<<9;
  325.   i=llseek(lieu->disk,pos,SEEK_SET);
  326.   if(i==-1)
  327.     return -1;
  328.   if(write(lieu->disk, nom_buffer, nbr_secteur*0x200)<0)
  329.     return -1;
  330.   return 0;
  331. #else
  332.   return 1;
  333. #endif
  334. }
  335.  
  336. int hd_read2(t_param_disk_cst disk_car,const uint nbr_secteur, void *nom_buffer, t_diskext_cst lieu)
  337. {
  338.   int i;
  339.   loff_t pos;
  340.   pos=((loff_t) get_LBA_part(disk_car,lieu))<<9;
  341.   i=llseek(lieu->disk,pos,SEEK_SET);
  342.   if(i==-1)
  343.     return -1;
  344.   read(lieu->disk, nom_buffer, nbr_secteur*0x200);
  345.   return 0;
  346. }
  347.  
  348. int hd_write2(t_param_disk_cst disk_car,const uint nbr_secteur, void *nom_buffer, t_diskext_cst lieu)
  349. {
  350. #ifdef LINUX_WRITE
  351.   int i;
  352.   loff_t pos;
  353.   pos=((loff_t) get_LBA_part(disk_car,lieu))<<9;
  354.   i=llseek(lieu->disk,pos,SEEK_SET);
  355.   if(i==-1)
  356.     return -1;
  357.   if(write(lieu->disk, nom_buffer, nbr_secteur*0x200)<0)
  358.     return -1;
  359.   return 0;
  360. #else
  361.   return 1;
  362. #endif
  363. }
  364.  
  365. void test_disk_availability(int * nbr_disk,t_param_disk param_disk[NBR_DISK_MAX], char *device);
  366. void test_disk_availability(int * nbr_disk,t_param_disk param_disk[NBR_DISK_MAX], char *device)
  367. {
  368.   struct hd_geometry geometry;
  369.   int hd_h = open(device, open_mode);
  370.   if(hd_h>0)
  371.   {
  372.     /* Little trick from Linux fdisk */
  373.     /* Blocks are visible in more than one way:
  374.        e.g. as block on /dev/hda and as block on /dev/hda3
  375.        By a bug in the Linux buffer cache, we will see the old
  376.        contents of /dev/hda when the change was made to /dev/hda3.
  377.        In order to avoid this, discard all blocks on /dev/hda. */
  378.     ioctl(hd_h, BLKFLSBUF);    /* ignore errors */
  379.                     /* e.g. Permission Denied */
  380.     if (!ioctl(hd_h, HDIO_GETGEO, &geometry))
  381.     { /* I can get the geometry */
  382.       param_disk[*nbr_disk]->name=MALLOC(strlen(device)+1);
  383.       strcpy(param_disk[*nbr_disk]->name,device);
  384.       param_disk[*nbr_disk]->CHS.cylinder= geometry.cylinders-1;
  385.       param_disk[*nbr_disk]->CHS.head=geometry.heads-1;
  386.       param_disk[*nbr_disk]->CHS.sector= geometry.sectors;
  387.       param_disk[*nbr_disk]->disk= hd_h;
  388.       (*nbr_disk)++;
  389.     }
  390.     else
  391.       close(hd_h);
  392.   }
  393. }
  394.  
  395. int hd_parse(t_param_disk param_disk[NBR_DISK_MAX],const int debug)
  396. {
  397.   int i;
  398.   char device_ide[]="/dev/hda";
  399.   char device_scsi[]="/dev/sda";
  400.   char device_ida[]="/dev/ida/c0d0";
  401.   int nbr_disk=0;
  402.   /* Disk IDE */
  403.   for(i=0;i<8;i++)
  404.   {
  405.     device_ide[strlen(device_ide)-1]='a'+i;
  406.     test_disk_availability(&nbr_disk,param_disk, device_ide);
  407.   }
  408.   /* Disk SCSI */
  409.   for(i=0;i<8;i++)
  410.   {
  411.     device_scsi[strlen(device_scsi)-1]='a'+i;
  412.     test_disk_availability(&nbr_disk,param_disk, device_scsi);
  413.   }
  414.   /* Device RAID Compaq */
  415.   test_disk_availability(&nbr_disk,param_disk, device_ida);
  416.   return nbr_disk;
  417. }
  418. #else
  419. #include <unistd.h>
  420. #include <sys/ioctl.h>
  421. #include <fcntl.h> 
  422. #include <sys/disklabel.h>
  423. #include "types.h"
  424. #include "common.h"
  425. #include "fnctdsk.h"
  426. #include "hdaccess.h"
  427.  
  428. int hd_read(t_param_disk_cst disk_car,const uint nbr_secteur, void *nom_buffer, t_disk_cst lieu)
  429. {
  430.   int i;
  431.   off_t pos;
  432.   pos=((off_t) get_LBA(disk_car,lieu))<<9;
  433.   printf("hd_read at %ld\n", pos);
  434.   i=lseek(lieu->disk,pos,SEEK_SET);
  435.   if(i==-1)
  436.     return -1;
  437.   if(read(lieu->disk, nom_buffer, nbr_secteur*0x200)==-1)
  438.     return -1;
  439.   return 0;
  440. }
  441.  
  442. int hd_write(t_param_disk_cst disk_car,const uint nbr_secteur, void *nom_buffer, t_disk_cst lieu)
  443. {
  444. #ifdef LINUX_WRITE
  445.   int i;
  446.   off_t pos;
  447.   pos=((off_t) get_LBA(disk_car,lieu))<<9;
  448.   i=lseek(lieu->disk,pos,SEEK_SET);
  449.   if(i==-1)
  450.     return -1;
  451.   if(write(lieu->disk, nom_buffer, nbr_secteur*0x200)<0)
  452.     return -1;
  453.   return 0;
  454. #else
  455.   return 1;
  456. #endif
  457. }
  458.  
  459. int hd_read2(t_param_disk_cst disk_car,const uint nbr_secteur, void *nom_buffer, t_diskext_cst lieu)
  460. {
  461.   int i;
  462.   off_t pos;
  463.   pos=((off_t) get_LBA_part(disk_car,lieu))<<9;
  464.   i=lseek(lieu->disk,pos,SEEK_SET);
  465.   if(i==-1)
  466.     return -1;
  467.   read(lieu->disk, nom_buffer, nbr_secteur*0x200);
  468.   return 0;
  469. }
  470.  
  471. int hd_write2(t_param_disk_cst disk_car,const uint nbr_secteur, void *nom_buffer, t_diskext_cst lieu)
  472. {
  473. #ifdef LINUX_WRITE
  474.   int i;
  475.   off_t pos;
  476.   pos=((off_t) get_LBA_part(disk_car,lieu))<<9;
  477.   i=lseek(lieu->disk,pos,SEEK_SET);
  478.   if(i==-1)
  479.     return -1;
  480.   if(write(lieu->disk, nom_buffer, nbr_secteur*0x200)<0)
  481.     return -1;
  482.   return 0;
  483. #else
  484.   return 1;
  485. #endif
  486. }
  487.  
  488. void test_disk_availability(int * nbr_disk,t_param_disk param_disk[NBR_DISK_MAX], char *device);
  489. void test_disk_availability(int * nbr_disk,t_param_disk param_disk[NBR_DISK_MAX], char *device)
  490. {
  491.   struct disklabel geometry;
  492.   int hd_h = open(device, open_mode);
  493.   if(hd_h>0)
  494.   {
  495.     if (!ioctl(hd_h, DIOCGDINFO, &geometry))
  496.     { /* I can get the geometry */
  497.       param_disk[*nbr_disk]->name=MALLOC(strlen(device)+1);
  498.       strcpy(param_disk[*nbr_disk]->name,device);
  499. /*
  500.       param_disk[*nbr_disk]->CHS.cylinder= geometry.cylinders-1;
  501.       param_disk[*nbr_disk]->CHS.head=geometry.heads-1;
  502.       param_disk[*nbr_disk]->CHS.sector= geometry.sectors;
  503.  */
  504.       param_disk[*nbr_disk]->CHS.cylinder=geometry.d_ncylinders-1;
  505.       param_disk[*nbr_disk]->CHS.head=geometry.d_ntracks-1;
  506.       param_disk[*nbr_disk]->CHS.sector=geometry.d_nsectors;
  507.       param_disk[*nbr_disk]->disk= hd_h;
  508.       (*nbr_disk)++;
  509.     }
  510.     else
  511.       close(hd_h);
  512.   }
  513. }
  514.  
  515. int hd_parse(t_param_disk param_disk[NBR_DISK_MAX],const int debug)
  516. {
  517.   int i;
  518.   char device_ide[]="/dev/rwd0";
  519.   char device_scsi[]="/dev/rda0";
  520.   char device_optdisk[]="/dev/rod0";
  521.   int nbr_disk=0;
  522.   /* Disk IDE */
  523.   for(i=0;i<8;i++)
  524.   {
  525.     device_ide[strlen(device_ide)-1]='0'+i;
  526.     test_disk_availability(&nbr_disk,param_disk, device_ide);
  527.   }
  528.   /* Disk SCSI */
  529.   for(i=0;i<8;i++)
  530.   {
  531.     device_scsi[strlen(device_scsi)-1]='0'+i;
  532.     test_disk_availability(&nbr_disk,param_disk, device_scsi);
  533.   }
  534.   /* optical disks */
  535.   for(i=0;i<8;i++)
  536.   {
  537.     device_optdisk[strlen(device_scsi)-1]='a'+i;
  538.     test_disk_availability(&nbr_disk,param_disk, device_optdisk);
  539.   } 
  540.   return nbr_disk;
  541. }
  542. #endif
  543.